#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <unistd.h>
#include "smartpipe.h"

using namespace std;
using namespace sp;

char* DATA_SOURCE;
char* DATA_TARGET;

int main(){
    /* 解析参数 */
    string video_path = "/data/lx/SmartPipe/data_source/videos/0.mp4"; // 视频路径
    string save_path = "/data/lx/SmartPipe/apps/car_license_plate_detect/output.avi";  // 输出路径
    long cnt = 800;           // 处理帧数
    // 声明共享内存管理对象
    SharedMemoryManager smm;
    Gpu_SharedMemoryManager gpu_smm;
    // 创建输入输出的视频缓冲区
    SharedMemoryPool input_video_pool = smm.createSharedMemoryPool("input_video", Cv_Mat_Data_3840_2160_Memory, cnt);
    SharedMemoryPool output_video_pool = smm.createSharedMemoryPool("output_video", Cv_Mat_Data_960_540_Memory, cnt);
    char* input_video_data_ptr = input_video_pool.getDataPtr();
    char* output_video_data_ptr = output_video_pool.getDataPtr();
    Image::Gen::genFromDisk f_start(video_path, input_video_data_ptr, cnt, 30, 3840, 2160);
    f_start.run();
    // 构造app
    Function* f0 = new Image::Gen::genFromMemory(input_video_data_ptr, cnt, 30, 3840, 2160);
    Function* f1 = new Image::Resize::resize(640, 384);
    Function* f2 = new Model::Yolo::yolo_preprocess(640, 384);
    Function* f3 = new Model::Group::groupByBatch(8);
    Function* f4 = new Model::Trans::transferToDeviceMemory();
    Function* f5 = new Model::Yolo::yolo_inference(640, 384);
    Function* f6 = new Model::Trans::transferToHostMemory();
    Function* f7 = new Model::Split::splitByShape();
    Function* f8 = new Model::Yolo::yolo_postprocess(640, 384);
    Function* f9 = new Image::Crop::cropWithInput(0);
    Function* f10 = new Image::Resize::resize(320, 320);
    Function* f11 = new Model::Retinanet::retinanet_preprocess();
    Function* f12 = new Model::Group::groupByBatch(8);
    Function* f13 = new Model::Trans::transferToDeviceMemory();
    Function* f14 = new Model::Retinanet::retinanet_inference();
    Function* f15 = new Model::Trans::transferToHostMemory();
    Function* f16 = new Model::Split::splitByShape();
    Function* f17 = new Model::Retinanet::retinanet_postprocess();
    Function* f18 = new Image::Crop::cropWithInput(1);
    Function* f19 = new Image::Resize::resize(94, 24);
    Function* f20 = new Image::Save::save(save_path, output_video_data_ptr, cnt, 30, 94, 24);
    // 连接逻辑关系
    connect(f0, f9);
    connect(f10, f18);
    connectOneByOne(21, f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20);
    // 部署表
    map<short, vector<Function*>> Fs_map;
    Fs_map[0] = {f0};
    Fs_map[1] = {f1, f9};
    Fs_map[2] = {f2, f8, f11, f17};
    Fs_map[3] = {f3, f7, f12, f16};
    Fs_map[4] = {f4, f6, f13, f15};
    Fs_map[5] = {f5, f14};
    Fs_map[6] = {f10, f18, f19};
    Fs_map[7] = {f20};
    // 建立App
    App app(0, Fs_map, &smm, &gpu_smm);
    app.check();
    app.printMsg();
    app.init();
    sleep(30);
    app.run();
    app.waitForComplete();
    smm.check();
    // 将视频写入磁盘
    Image::Save::save f_end(save_path, output_video_data_ptr, cnt, 30, 94, 24);
    f_end.run();
    return 0;
}